package com.asiainfo.indb.control;

import com.asiainfo.indb.view.LogPanel;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;


/**
 * 日志服务，包含统计信息
 *
 * @author zym
 * @date 2019-10-18 11:01
 */
public class LogService {


    /**
     * 当前日志服务所依赖的入库主服务
     */
    private InDbService inDbService;

    private LogPanel logDialog;

    /**
     * 用于确认是否渲染完成
     */
    private BlockingQueue<String> msgQueue;

    /**
     * 退出标志
     */
    private volatile AtomicBoolean exit;

    /**
     * 记录总次数
     */
    private volatile AtomicLong allTask = new AtomicLong();

    /**
     * 开始统计时间
     */
    private long startTime;

    /**
     * 统计计数器
     */
    private CountDownLatch cdl;

    public LogService(InDbService service) {
        this.inDbService = service;
        this.msgQueue = new LinkedBlockingQueue<>();
        this.exit = new AtomicBoolean(false);
        this.logDialog = new LogPanel(this);

        // 启动线程
        ThreadFactory.run("logService", () -> {
            while (!exit.get()) {
                if (logDialog != null && logDialog.ready()) {
                    while (msgQueue.peek() != null) {
                        logDialog.append(msgQueue.poll());
                    }
                }

                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    // do nothing
                }
            }

            inDbService.stop();
            logDialog.dispose();
        });
    }

    /**
     * 输出日志
     *
     * @param msg 日志
     */
    public void report(String msg) {
        if (msgQueue != null) {
            msgQueue.offer(msg);
        }
    }

    /**
     * 停止日志服务
     * 当用户点击日志窗口关闭按钮的时候调用，会同时停止入库服务
     */
    public void dispose() {
        this.exit.compareAndSet(false, true);
    }

    /**
     * 开始入库
     *
     * @param num 入库线程数量
     */
    public void beginInDb(int num) {
        this.startTime = System.currentTimeMillis();
        this.cdl = new CountDownLatch(num);
    }

    public void endInDb() {
        if (this.cdl != null) {
            await();
            report("入库总数量：" + allTask.get() + "条");
            report("入库完成，耗时：" + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - startTime) + "秒");
        }
    }

    /**
     * 处理的条数
     *
     * @param num 条数
     */
    public void deal(long num) {
        allTask.addAndGet(num);
    }

    /**
     * 完成一项
     */
    public void done() {
        if (this.cdl != null) {
            report("工作线程：" + Thread.currentThread().getName() + "处理完成");
            this.cdl.countDown();
        }
    }

    /**
     * 等待
     */
    public void await() {
        if (this.cdl != null) {
            try {
                this.cdl.await();
            } catch (InterruptedException e) {
                report("系统中断！");
            }
        }
    }
}